#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
@File    : run.py
@Description : 测试执行入口，用于执行测试并生成报告
'''

import os
import sys
import time
import pytest
import argparse
import subprocess
from datetime import datetime

# 导入项目模块
from config.settings import config
from utils.log_handler import get_logger
from utils.dingtalk_handler import DingTalkHandler
from utils.json_handler import JsonHandler


# 创建日志记录器
logger = get_logger("run")


def parse_args():
    """
    解析命令行参数
    
    Returns:
        解析后的参数对象
    """
    parser = argparse.ArgumentParser(description="接口自动化测试执行入口")
    parser.add_argument(
        "-m", "--markers", 
        help="指定要运行的测试标记，如smoke、regression等"
    )
    parser.add_argument(
        "-k", "--keyword", 
        help="指定要运行的测试关键字"
    )
    parser.add_argument(
        "-e", "--env", 
        choices=["dev", "test", "prod"], 
        default=config.environment,
        help="指定测试环境"
    )
    parser.add_argument(
        "-r", "--report", 
        action="store_true", 
        help="是否生成HTML报告"
    )
    parser.add_argument(
        "-d", "--dingtalk", 
        action="store_true", 
        help="是否发送钉钉通知"
    )
    parser.add_argument(
        "-c", "--cases", 
        help="指定要运行的测试用例文件或目录"
    )
    
    return parser.parse_args()


def run_tests(args):
    """
    运行测试
    
    Args:
        args: 命令行参数对象
        
    Returns:
        测试结果，0表示成功，非0表示失败
    """
    # 构建pytest命令参数
    pytest_args = []
    
    # 添加标记
    if args.markers:
        pytest_args.extend(["-m", args.markers])
    
    # 添加关键字
    if args.keyword:
        pytest_args.extend(["-k", args.keyword])
    
    # 添加测试用例
    if args.cases:
        pytest_args.append(args.cases)
    else:
        pytest_args.append("testcases")
    
    # 添加allure结果目录
    allure_results_dir = os.path.join(config.allure_results_dir)
    os.makedirs(allure_results_dir, exist_ok=True)
    pytest_args.extend(["--alluredir", allure_results_dir])
    
    # 添加其他参数
    pytest_args.extend(["-v", "--clean-alluredir"])
    
    # 记录测试开始时间
    start_time = time.time()
    logger.info(f"开始运行测试，参数: {' '.join(pytest_args)}")
    
    # 运行测试
    result = pytest.main(pytest_args)
    
    # 记录测试结束时间和耗时
    end_time = time.time()
    duration = end_time - start_time
    logger.info(f"测试运行完成，耗时: {round(duration, 2)}秒，结果: {result}")
    
    # 生成HTML报告
    if args.report:
        generate_html_report(allure_results_dir)
    
    # 生成Allure报告
    generate_allure_report(allure_results_dir)
    
    return result


def generate_html_report(allure_results_dir):
    """
    生成HTML报告
    
    Args:
        allure_results_dir: Allure结果目录
    """
    try:
        html_report_dir = os.path.join(config.html_report_dir)
        os.makedirs(html_report_dir, exist_ok=True)
        
        logger.info(f"生成HTML报告，目录: {html_report_dir}")
        
        # 使用pytest-html生成HTML报告
        html_report_path = os.path.join(html_report_dir, f"report_{datetime.now().strftime('%Y%m%d%H%M%S')}.html")
        pytest.main(["--html", html_report_path, "--self-contained-html"])
        
        logger.info(f"HTML报告生成成功: {html_report_path}")
    except Exception as e:
        logger.error(f"生成HTML报告失败: {str(e)}")


def generate_allure_report(allure_results_dir):
    """
    生成Allure报告
    
    Args:
        allure_results_dir: Allure结果目录
    """
    try:
        allure_report_dir = os.path.join(config.report_dir, "allure_report")
        os.makedirs(allure_report_dir, exist_ok=True)
        
        logger.info(f"生成Allure报告，目录: {allure_report_dir}")
        
        # 使用allure命令生成报告
        cmd = f"allure generate {allure_results_dir} -o {allure_report_dir} --clean"
        process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        
        if process.returncode == 0:
            logger.info(f"Allure报告生成成功: {allure_report_dir}")
            logger.info(f"可以使用命令查看报告: allure serve {allure_results_dir}")
        else:
            logger.error(f"生成Allure报告失败: {stderr.decode('utf-8')}")
    except Exception as e:
        logger.error(f"生成Allure报告失败: {str(e)}")


def main():
    """
    主函数
    """
    # 解析命令行参数
    args = parse_args()
    
    # 运行测试
    result = run_tests(args)
    
    # 返回测试结果
    return result


if __name__ == "__main__":
    sys.exit(main())